package com.cpe.web.controller.member;

import static com.sql.data.domain.user.UserRespCode.INVALID_MOBILE_CHECKCODE;
import static com.sql.data.domain.user.UserRespCode.INVALID_TOKEN;
import static com.sql.data.domain.user.UserRespCode.PERMISSION_DENY;
import static com.sql.data.response.CommonRespCode.EXCEPTION;
import static com.sql.data.response.CommonRespCode.RESOURCE_NOT_FOUND;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
import static org.springframework.web.bind.annotation.RequestMethod.PUT;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.cpe.data.domain.member.Member;
import com.cpe.data.domain.member.MemberForm;
import com.cpe.data.domain.member.MemberRespCode;
import com.cpe.data.domain.student.Student;
import com.cpe.data.domain.student.StudentForm;
import com.cpe.data.domain.student.StudentRespCode;
import com.cpe.repository.mapper.member.MemberMapper;
import com.cpe.repository.mapper.student.StudentMapper;
import com.cpe.service.account.AccountService;
import com.cpe.service.member.MemberService;
import com.cpe.service.student.StudentService;
import com.cpe.service.wechat.WechatService;
import com.cpe.transfer.member.MemberTransfer;
import com.cpe.transfer.student.StudentTransfer;
import com.cpe.web.controller.AbstractController;
import com.google.common.base.Objects;
import com.sql.data.response.CommonRespCode;
import com.sql.data.response.JsonResponse;
import com.wechat.api.WechatAPI;
import com.wechat.data.WebAccessToken;
import com.wechat.data.user.LoginForm;
import com.wechat.data.user.UserInfo;

import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping("/members")
@Transactional
public class AccountController extends AbstractController {

	@Resource
	private MemberMapper memberMapper;

	@Resource
	private MemberService memberService;

	@Resource
	private MemberTransfer memberTransfer;

	@Resource
	private AccountService accountService;

	@Resource
	private StudentMapper studentMapper;

	@Resource
	private StudentService studentService;

	@Resource
	private WechatService wechatService;

	@Resource
	private WechatAPI wechatAPI;

	@Resource
	private StudentTransfer studentTransfer;

	/**
	 * 微信网页授权登录
	 */
	@Transactional
	@RequestMapping(value = "/wechat/login", method = POST)
	public JsonResponse loginOnWeixin(@RequestBody LoginForm loginForm, ModelMap modelMap, HttpSession session,
			@RequestHeader(required = false) String openid) {
		Member member = (Member) session.getAttribute("loginer");

		int flag = 0;
		if (member != null) {
			// 从数据库拉取最新的信息，解决更换用户角色后无法实时看到效果
			member = memberMapper.findByOpenid(member.getOpenid());
			// if (member != null) { // 防止管理员恶意物理删除该用户，出现这种情况只能往下走，重新注册该用户
			// modelMap.addAttribute("loginer", member);
			// return JsonResponse.ok(memberTransfer.toInfo(member));
			// } else {
			// flag = 1;
			// }
			if (member == null) {
				flag = 1;
			}
		}

		// 用code换取网页授权access_token
		WebAccessToken webAccessToken = wechatAPI.getWebAccessToken(loginForm.getCode());

		// 如果网页access_token失效，则尝试用请求头中的openid来获取用户信息
		if (StringUtil.isBlank(webAccessToken.getOpenid())) {
			if (StringUtil.isBlank(openid)) {
				return JsonResponse.custom(MemberRespCode.CANNOT_GET_INFO);
			}
			member = memberMapper.findById(openid);
			if (member == null) {
				return JsonResponse.custom(MemberRespCode.CANNOT_GET_INFO);
			}
			flag = 2;
		}

		if (flag == 0 && member == null) {
			member = memberMapper.findByOpenid(webAccessToken.getOpenid());
			log.debug("member = " + member);
		}

		if (member == null) {
			// 注册该用户到自己的平台里
			UserInfo userInfo = wechatAPI.getUserInfo(webAccessToken.getOpenid());
			member = new Member();
			member.setAddress(userInfo.address());
			member.setOpenid(userInfo.getOpenid());
			member.setName(userInfo.getOpenid());
			member.setNickName(userInfo.getNickname());
			member.setHeadImgurl(userInfo.getHeadimgurl());
			member.setBlacklistStatus(0);
			member.setCreateTime(new Date());
			try {
				memberMapper.insert(member);
			} catch (Exception e) {
				// 主键重复，说明关注事件的用户异步注册完成时刻早于该请求
				log.error(e.getMessage(), e);
			} finally {
				log.debug("openid = " + webAccessToken.getOpenid());
				member = memberMapper.findByOpenid(webAccessToken.getOpenid());
				Assert.notNull(member);
			}
		} else if (StringUtil.isBlank(member.getHeadImgurl())) {
			// 更新该用户信息
			UserInfo userInfo = wechatAPI.getUserInfo(webAccessToken.getOpenid());
			if (StringUtil.isNotBlank(userInfo.getHeadimgurl())) {
				member.setHeadImgurl(userInfo.getHeadimgurl());
				memberMapper.updateById(member);
			}
		}
		modelMap.addAttribute(webAccessToken).addAttribute("loginer", member);
		return JsonResponse.ok(memberTransfer.toInfo(member));
	}

	/**
	 * 测试登录
	 */
	@RequestMapping(value = "/debug/login", method = POST)
	public JsonResponse testLogin(ModelMap modelMap, HttpSession session) {
		Member member = memberMapper.findByOpenid("oalBnxC53p_rlY_f1dQ1LrBg-mEw");
		modelMap.addAttribute("loginer", member);
		return JsonResponse.ok(memberTransfer.toInfo(member));
	}

	/**
	 * 查询登录者信息
	 */
	@RequestMapping(value = "/loginer/detail", method = GET)
	public JsonResponse loginerInfo(HttpSession session, @RequestHeader String openid) {
		Member member = (Member) session.getAttribute("loginer");
		if (member == null) {
			// 尝试从Header里读取openid
			member = memberMapper.findByOpenid(openid);
			if (member == null) {
				return JsonResponse.custom(INVALID_TOKEN);
			}
		}
		return JsonResponse.ok(memberTransfer.toInfo(member));
	}

	/**
	 * 更新个人基本信息
	 */
	@RequestMapping(value = "/loginer", method = PUT)
	public JsonResponse updateMyInfo(HttpSession session, @RequestHeader String openid, @RequestBody MemberForm form,
			ModelMap modelMap) {
		Member member = (Member) session.getAttribute("loginer");
		if (member == null) {
			// 尝试从Header里读取openid
			member = memberMapper.findByOpenid(openid);
			if (member == null) {
				return JsonResponse.custom(INVALID_TOKEN);
			}
		}
		try {
			member = memberService.updateLoginer(member, form);
			modelMap.addAttribute("loginer", member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return JsonResponse.custom(EXCEPTION);
		}
		return JsonResponse.ok(member);
	}

	/**
	 * 获取验证码
	 */
	@RequestMapping(value = "/loginer/{mobile}/check_code", method = GET)
	public JsonResponse getCheckCode(@PathVariable String mobile) {
		// 数据库校验
		Member m = memberMapper.findByMobile(mobile);
		if (m != null && m.getMobileStatus() == 1) {
			return JsonResponse.custom(MemberRespCode.MOBILE_REGISTED);
		}
		try {
			String checkCode = accountService.getCheckCode(mobile);
			return JsonResponse.ok(checkCode);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return JsonResponse.custom(EXCEPTION);
		}
	}

	/**
	 * 验证并设置手机号
	 */
	@Transactional
	@RequestMapping(value = "/loginer/{mobile}/validation", method = PUT)
	public JsonResponse setMobile(@RequestBody String checkCode, @PathVariable String mobile, HttpSession session,
			@RequestHeader String openid, ModelMap modelMap) {
		// 登录校验
		Member member = (Member) session.getAttribute("loginer");
		if (member == null) {
			// 尝试从Header里读取openid
			member = memberMapper.findByOpenid(openid);
			if (member == null) {
				return JsonResponse.custom(INVALID_TOKEN);
			}
		}

		// 参数校验
		if (StringUtil.isBlank(checkCode)) {
			return JsonResponse.custom(CommonRespCode.INVALID_PARAMETER);
		}
		if (!accountService.validateCheckCode(checkCode, mobile)) {
			return JsonResponse.custom(INVALID_MOBILE_CHECKCODE);
		}

		String operateFlag = "firstBind";
		if (Objects.equal(member.getMobile(), mobile)) {
			if (member.getMobileStatus() == 1) {
				return JsonResponse.custom(MemberRespCode.MOBILE_REGISTED);
			} else {
				operateFlag = "validate";
			}
		}

		if (!Objects.equal(member.getMobile(), mobile)) {
			operateFlag = "modify";
		}
		try {
			switch (operateFlag) {
			case "validate":
			case "add": {
				// 绑定手机号
				member = accountService.bindMobile(member.getId(), mobile);
				if (member != null) {
					// 查询未绑定的孩子
					List<Student> newStudents = studentMapper.findByParentMobile(mobile);
					// 绑定新孩子
					for (Student student : newStudents) {
						if (!Objects.equal(student.getParentId(), member.getId())) {
							student.setParentId(member.getId());
							studentMapper.updateById(student);
						}
					}
				}
				break;
			}
			case "modify": {
				// 查询已绑定的孩子
				List<Student> oldStudents = studentMapper.findByParentId(member.getId());
				// 绑定手机号
				member = accountService.bindMobile(member.getId(), mobile);
				if (member != null) {
					// 查询未绑定的孩子
					List<Student> newStudents = studentMapper.findByParentMobile(member.getMobile());
					// 更新原来绑定的孩子
					for (Student student : oldStudents) {
						if (!Objects.equal(student.getParentMobile(), mobile)) {
							student.setParentMobile(mobile);
							studentMapper.updateById(student);
						}
					}
					// 绑定新孩子
					for (Student student : newStudents) {
						if (!Objects.equal(student.getParentId(), member.getId())) {
							student.setParentId(member.getId());
							studentMapper.updateById(student);
						}
					}
				}
				break;
			}
			default:
				break;
			}
			if (member != null && StringUtil.isNotBlank(member.getMobile()) && member.getMobileStatus() == 1) {
				modelMap.addAttribute("loginer", member);
				return JsonResponse.ok(memberTransfer.toInfo(member));
			} else {
				return JsonResponse.custom(EXCEPTION);
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return JsonResponse.custom(EXCEPTION);
		}
	}

	/**
	 * 绑定孩子
	 */
	@RequestMapping(value = "/loginer/students/{serialNumber}/bind", method = PUT)
	public JsonResponse bindChildren(@PathVariable String serialNumber, HttpSession session,
			@RequestHeader String openid) {
		Member member = (Member) session.getAttribute("loginer");
		if (member == null) {
			// 尝试从Header里读取openid
			member = memberMapper.findByOpenid(openid);
			if (member == null) {
				return JsonResponse.custom(INVALID_TOKEN);
			}
		}

		// 参数校验
		if (member.getRole() != 0) {
			return JsonResponse.custom(PERMISSION_DENY);
		}
		if (StringUtil.isBlank(member.getMobile()) || member.getMobileStatus() == 0) {
			return JsonResponse.custom(StudentRespCode.INVALID_MOBILE);
		}

		// 数据库校验
		Student student = new Student();
		student.setSerialNumber(serialNumber);
		student = studentMapper.findOne(student);
		if (student == null) {
			return JsonResponse.custom(RESOURCE_NOT_FOUND);
		}
		if (StringUtil.isNotBlank(student.getParentId())) {
			return JsonResponse.custom(StudentRespCode.BINDIND_EXIST);
		}
		try {
			studentService.updateParent(student, member.getId());
			return JsonResponse.ok();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return JsonResponse.custom(EXCEPTION);
		}
	}

	@Transactional
	@RequestMapping(value = "/loginer/student/bind", method = POST)
	public JsonResponse bindChildren(HttpSession session, @RequestHeader String openid,
			@RequestBody StudentForm studentForm) {
		Member member = (Member) session.getAttribute("loginer");
		if (member == null) {
			// 尝试从Header里读取openid
			member = memberMapper.findByOpenid(openid);
			if (member == null) {
				return JsonResponse.custom(INVALID_TOKEN);
			}
		}

		// 参数校验
		Date birthday = studentForm.getBirthday();
		if (birthday.after(new Date())) {
			return JsonResponse.custom(StudentRespCode.INVALID_BIRTHDAY);
		}
		if (member.getRole() != 0) {
			return JsonResponse.custom(PERMISSION_DENY);
		}
		String mobile = member.getMobile();
		if (StringUtil.isBlank(mobile) || member.getMobileStatus() == 0) {
			return JsonResponse.custom(StudentRespCode.INVALID_MOBILE);
		} else {
			studentForm.setParentMobile(mobile);
		}
		studentForm.setCreatorRole(2);
		if (studentForm.stopCreate()) {
			return JsonResponse.invalid("缺少必输项！");
		}

		// 数据库校验
		List<Student> list = studentMapper.findByParentId(member.getId());
		if (list.size() >= 10) {
			return JsonResponse.custom(StudentRespCode.CHILD_NUM_UPTO_MAX);
		}

		Student studentQuery = new Student();
		studentQuery.setBirthday(studentForm.getBirthday());
		studentQuery.setSex(studentForm.getSex());
		studentQuery.setName(studentForm.getName());
		list = studentMapper.find(studentQuery);
		if (list.size() > 1) {
			return JsonResponse.custom(StudentRespCode.TOO_MANY_STUDENTS);
		}

		try {
			if (list.size() == 0) {
				// 没有该孩子信息，则录入数据库
				Student student = studentTransfer.toEntity(studentForm);
				student.setParentId(member.getId());
				studentService.addOne(student, false);
			} else {
				// 已有该孩子信息，则更新家长手机号
				studentService.updateParent(list.get(0), member.getId());
				return JsonResponse.ok();
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return JsonResponse.custom(EXCEPTION);
		}
		return JsonResponse.ok();
	}
}
